use std::os::fd::AsRawFd;
use tokio::net::*;
use tokio::runtime::*;

type Fd = TcpStream;

mod http;
use http::*;

async fn server_conn(conn: Fd, size: usize) {
    let _ = conn.set_linger(Some(Duration::default()));
    loop {
        let mut req = HttpReq::new();
        if let Err(_) = req.read(&conn).await {
            break;
        }

        let rsp = HttpRsp::new(size);
        if let Err(_) = rsp.write(&conn).await {
            break;
        }
    }
    unsafe { libc::shutdown(conn.as_raw_fd(), libc::SHUT_RDWR) };
}

async fn server(port: u16) {
    let size = hirun::runtime::env_unsigned::<usize>("http_body_size", 0, 10240);
    let addr = format!("127.0.0.1:{}", port);
    let server = match TcpListener::bind(addr).await {
        Ok(server) => server,
        Err(e) => {
            println!("tcp_server fail: {e:?}");
            return;
        }
    };
    loop {
        match server.accept().await {
            Ok((conn, _)) => {
                let _ = tokio::spawn(server_conn(conn, size));
            }
            Err(_e) => {}
        };
    }
}

use std::time::*;

fn main() {
            let rt = Builder::new_multi_thread()
                .enable_all()
                //.worker_threads(4)
                .build().unwrap();
    let _ = rt.block_on(server(2001));
}
